package com.test.A06;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

/*
    Aware 接口及 InitializingBean 接口
 */
public class A06 {
    private static final Logger log = LoggerFactory.getLogger(A06.class);

    public static void main(String[] args) {
    	test4();
    }
    
    /****
     * 使用实现接口的方法的话，就不会失效
     */
    public static void test4() {
    	   GenericApplicationContext context = new GenericApplicationContext();
    	   context.registerBean("myconfig2", MyConfig2.class); 
    	   context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
    	   context.registerBean(CommonAnnotationBeanPostProcessor.class);
    	   context.registerBean(ConfigurationClassPostProcessor.class); 
    	   context.refresh(); //执行的顺序 1. beanFactory 后处理器,  2. 添加 bean 后处理器, 3. 初始化单例
    	   context.close();
    	 
    	   }
    

   /***
             * 测试autowired失效的原因   原因是执行顺序有问题
    */
   public static void test3() {
   GenericApplicationContext context = new GenericApplicationContext();
   context.registerBean("myconfig1", MyConfig1.class); 
   context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
   context.registerBean(CommonAnnotationBeanPostProcessor.class);
   context.registerBean(ConfigurationClassPostProcessor.class); 
   context.refresh(); //执行的顺序 1. beanFactory 后处理器,  2. 添加 bean 后处理器, 3. 初始化单例
   context.close();
 
   }
    
    /****
           * 如果想要执行  @Autowired 和 @PostConstruct 需要加后处理器
     */
    public static void test2() {
   
   GenericApplicationContext context = new GenericApplicationContext();
   context.registerBean("myBean", MyBean.class); 
   context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
   context.registerBean(CommonAnnotationBeanPostProcessor.class);
   context.registerBean(ConfigurationClassPostProcessor.class); 
   context.refresh(); //执行的顺序 1. beanFactory 后处理器,  2. 添加 bean 后处理器, 3. 初始化单例
   context.close();
 
   }
    
    /***
     * 测试实现BeanNameAware, ApplicationContextAware, InitializingBean接口
     */
    public static void test1() {
    	 /*
        1. Aware 接口用于注入一些与容器相关信息, 例如
            a. BeanNameAware 注入 bean 的名字
            b. BeanFactoryAware 注入 BeanFactory 容器
            c. ApplicationContextAware 注入 ApplicationContext 容器
            d. EmbeddedValueResolverAware ${}

     */
    GenericApplicationContext context = new GenericApplicationContext();
    context.registerBean("myBean", MyBean.class); 

    /*
        2. 有同学说: b、c、d 的功能用 @Autowired 就能实现啊, 为啥还要用 Aware 接口呢
        简单地说:
            a. @Autowired 的解析需要用到 bean 后处理器, 属于扩展功能
            b. 而 Aware 接口属于内置功能, 不加任何扩展, Spring 就能识别
        某些情况下, 扩展功能会失效, 而内置功能不会失效

        例1: 你会发现用 Aware 注入 ApplicationContext 成功, 而 @Autowired 注入 ApplicationContext 失败
     */

    /*
        例2: Java 配置类在添加了 bean 工厂后处理器后,
            你会发现用传统接口方式的注入和初始化仍然成功, 而 @Autowired 和 @PostConstruct 的注入和初始化失败
     */

    context.refresh(); // 1. beanFactory 后处理器,  2. 添加 bean 后处理器, 3. 初始化单例
    context.close();

    /*
        学到了什么
            a. Aware 接口提供了一种【内置】 的注入手段, 可以注入 BeanFactory, ApplicationContext
            b. InitializingBean 接口提供了一种【内置】的初始化手段
            c. 内置的注入和初始化不受扩展功能的影响, 总会被执行, 因此 Spring 框架内部的类常用它们
     */
    }
}
